package com.xpec.c4.net;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.TreeMap;

import net.sf.cindy.Session;

import org.jboss.netty.channel.Channel;

import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.net.handler.ConsolidatingAutoFlusher;

public class XSENetSession
{
	private static final int DELAYTIME = 90;
	
	//cindy
	private Session mSession = null;
	
	//netty
	private Channel mChannel = null;
	private ConsolidatingAutoFlusher mAutoFlusher = null;
	
	private HashMap<String, Object> parameters = new HashMap<String, Object>();
	
	/////////////////////////////////////////////////////////////////////////
	
	public XSENetSession(Session session)
	{
		mSession = session;
	}
	
	public XSENetSession(Channel channel)
	{
		mChannel = channel;
		
		mAutoFlusher = (ConsolidatingAutoFlusher)mChannel.getPipeline().get("ConsolidatingAutoFlusher");
	}
	
	public void send(Object gameMessage, int priority)
	{
		//使用編譯最佳化
		if( XSENetGlobal.mLibType == XSENetConstant.LIB_CINDYMODE )
		{
			if( !mSession.isStarted() )
				return;
			
			synchronized(mSession)
			{
				mSession.send(gameMessage, priority);
			}
		}
		else if( XSENetGlobal.mLibType == XSENetConstant.LIB_NETTYMODE )
		{
			if( !mChannel.isConnected() )
				return;
			
			mChannel.write(gameMessage);
			
			//rowan:
			//mAutoFlusher.tryFlush();
		}
	}
	
	public void flush()
	{
		if( XSENetGlobal.mLibType == XSENetConstant.LIB_NETTYMODE )
		{
			//rowan:
			//mAutoFlusher.flush();

			//mIsSend.set(false);
		}
	}
	
	public XSENetFuture close()
	{
		//使用編譯最佳化
		if( XSENetGlobal.mLibType == XSENetConstant.LIB_CINDYMODE )
		{
			return new XSENetFuture(mSession.close());
		}
		else if( XSENetGlobal.mLibType == XSENetConstant.LIB_NETTYMODE )
		{
			return new XSENetFuture(mChannel.close());
		}
		
		return null;
	}
	
	/////////////////////////////////////////////////////////////////////////
	
//	private String mID;
//	
//	public void setID(String id)
//	{
//		mID = id;
//	}
//	public String getID()
//	{
//		return mID;
//	}

	private GUID mID;
	
	public void setID(GUID id)
	{
		mID = id;
	}
	public GUID getID()
	{
		return mID;
	}
	
	
//	//
//	private String mAccountID;
//	
//	public void setAccountID(String id)
//	{
//		mAccountID = id;
//	}
//	public String getAccountID()
//	{
//		return mAccountID;
//	}
	

	/////////////////////////////////////////////////////////////////////////
	
	//private static final FlushTimer mFlusher = new FlushTimer();
	//private final AtomicBoolean mIsSend = new AtomicBoolean(false);
	
	/*
	private void forward(long time)
	{
		if( mIsSend.compareAndSet(false, true) )
		{
			mFlusher.add(time, this);
		}
	}
	*/
	
	public static void initialize()
	{
		//為了保持數據發送的順序, 使用一個Thread 
		if( XSENetGlobal.mLibType == XSENetConstant.LIB_NETTYMODE )
		{
			/*
			Thread pThread = new Thread(mFlusher);
			pThread.setDaemon(true);
			pThread.start();
			*/
		}
	}

	public HashMap<String, Object> getParameters() {
		return parameters;
	}

	public void setParameters(HashMap<String, Object> parameters) {
		this.parameters = parameters;
	}
}

////////////////////////////////////////////////////////////////////////

class _FlushTimer implements Runnable
{
	private TreeMap<Long, ArrayList<XSENetSession>> mFlushPool = new TreeMap<Long, ArrayList<XSENetSession>>();
	
	public void add(long time, XSENetSession flusher)
	{

		 synchronized(mFlushPool)
		 {
			 ArrayList<XSENetSession> list = mFlushPool.get(time);
			 if( list == null )
			 {
				 list = new ArrayList<XSENetSession>();
				 mFlushPool.put(time, list);
			 }
			 list.add(flusher);
		 }
	}
	
	@Override
	public void run()
	{
		 long uNOW;
			
		 LinkedList<XSENetSession> flushList = new LinkedList<XSENetSession>();
		 
		 while( true )
		 {
			try
			{
				uNOW = System.currentTimeMillis();
				
				synchronized(mFlushPool)
				{
					if( mFlushPool.size() > 0 )
					{
						Iterator<Entry<Long, ArrayList<XSENetSession>>> itr = mFlushPool.entrySet().iterator();
						while( itr.hasNext() )
					    {
							Entry<Long, ArrayList<XSENetSession>> pairs = itr.next();
						    	
							long nCastTime = pairs.getKey();
							if( uNOW >= nCastTime )
							{
								flushList.addAll(pairs.getValue());
								itr.remove();
							}
							else
								break;
						}
					}
				}
				
				//
				if( flushList.size() > 0 )
				{
					for(XSENetSession flusher : flushList)
					{
						flusher.flush();
					}
						
					flushList.clear();
				}
					
				Thread.sleep(1);
			}
			catch (Exception e)
			{
				e.printStackTrace();
			}
		 }
	}
}